#pragma once
#ifndef _INSTANCE_H
#define _INSTANCE_H

#include "horse.h"
#include "utils.h"
#include "interfaces/instancei.h"

class Instance : public InstanceI
{

	

public:
	//2dim. vector of uns.ints..
	typedef std::vector<std::vector<unsigned> > penalties_t;
	typedef std::vector<Horse> horses_t;

	//default ctor for purposes of deserialization.
	//should not be used elsewhere
	Instance()
		: m_n(0), m_k(0), m_q(0), penalties(), horses()
	{}
		
	//Ctor s parametry.
	Instance(
		const unsigned _n, //velikost desky
		const unsigned _k, //pocet konu
		const unsigned _q, //pocet nahodnych tahu
		const penalties_t& _pens, //vektor vektoru celych cisel
		const horses_t& _hors //vektor souradnic (konu)
		)
		: m_n(_n),m_k(_k),m_q(_q)
	{
		checkNumParams();
		penalties = _pens;
		checkPensVector();
		horses = _hors;
		checkHorsVector();
	}

	
	//returns penalty for given coordinates
	//performs bounds checking
	virtual unsigned getPenalty(const unsigned x, const unsigned y) const
	{
		return penalties.at(y).at(x);
	}

	virtual unsigned getPenalty(const utils::coords_t c) const
	{
		return getPenalty(c.first, c.second);
	}


	// returns horses
	virtual const horses_t& getHorses() const {
		return horses;
	}
	
	//velikost sachovnice
	virtual unsigned n() const
	{
		return m_n;
	}

	//pocet jezdcu
	virtual unsigned k() const
	{
		return m_k;
	}

	//max. pocet tahu do reseni
	virtual unsigned q() const
	{
		return m_q;
	}

	virtual ~Instance()
	{}

private:

	unsigned m_n; //velikost sachovnice
	
	unsigned m_k; //pocet jezdcu
	
	unsigned m_q; //max. pocet tahu do reseni

	//vector of vectors of penalties
	penalties_t penalties;

	//vector of horses
	horses_t horses;


	//checks given params - board size, horses count, turns count
	//throws an exception if failed
	void checkNumParams()
	{
		if (m_n<5 || m_k<m_n || m_k>m_n*(m_n+1)/2 || m_q<m_n || m_q>m_n*m_n)
		{
			throw "numeric parameters of this instance are out of allowed range";
		}
	}


	//check penalties vector
	//throws an exception if failed
	void checkPensVector()
	{
		if (penalties.size() != m_n)
		{
			throw "invalid column size";
		}
		for(unsigned i = 0; i < penalties.size(); i++)
		{
			if(penalties[i].size() != m_n)
			{
				throw "invalid row length";
			}
		}
	}

	//check horses vector
	//throws an exception if failed
	void checkHorsVector()
	{
		if (horses.size() != m_k)
		{
			throw "invalid horses count";
		}
	}
};

#endif //Instance.h
